<template>
  <div class="app-container">
    <el-card>
      <div class="mb8 flex-container">
        <div class="sift_left">
          <el-input v-model="state.listQuery.name" placeholder="请输入用例名称" style="max-width: 180px"></el-input>
          <el-button type="primary" class="ml10" @click="getList">
            查询
          </el-button>
          <el-button type="success" class="ml10" @click="onOpenSaveOrUpdate('save', null)">
            新增
          </el-button>
        </div>
        <div class="sift_right">
          <el-select
              v-model="state.listQuery.project_id"
              placeholder="选择项目"
              clearable
              filterable
              style="width: 100%;"
              @change="getList">
            <el-option label="全部项目" value=''>
              全部项目
            </el-option>
            <el-option
                v-for="project in state.projectList"
                :key="project.id"
                :label="project.name"
                :value="project.id">
              {{ project.name }}
            </el-option>
          </el-select>
        </div>
      </div>


      <!--  tool  -->
      <div class="mb8 mt8">
        <el-checkbox v-model="state.oneSelf" @change="oneSelfChange">
          只看自己创建
        </el-checkbox>


        <el-button type="primary"
                   link
                   class="ml8"
                   :disabled="state.selectionData.length === 0"
                   style="vertical-align: text-bottom"
                   @click="onOpenBatchRunPage">
          <el-icon>
            <ele-CaretRight/>
          </el-icon>
          批量执行
        </el-button>
        <el-button type="success"
                   link
                   class="ml8"
                   style="vertical-align: text-bottom"
                   @click="openImportPage">
          <el-icon>
            <ele-FolderAdd/>
          </el-icon>
          导入接口
        </el-button>
      </div>

      <!-- API List -->
      <div>
        <z-table
            :columns="state.columns"
            :data="state.listData"
            ref="tableRef"
            v-model:page-size="state.listQuery.pageSize"
            v-model:page="state.listQuery.page"
            :total="state.total"
            @pagination-change="getList"
            @selection-change="selectionChange"
        >
        </z-table>
      </div>
    </el-card>

    <!-- 运行用例  -->
    <el-dialog
        draggable
        v-model="state.showRunPage"
        width="600px"
        top="8vh"
        title="运行用例"
        :close-on-click-modal="false">
      <el-form :model="state.runForm" label-width="70px">
        <el-form-item label="运行模式" prop="run_mode">
          <el-select v-model="state.runForm.run_mode" placeholder="选择运行模式" filterable style="width:100%">
            <el-option :value="10" label="同步运行(同步执行,等待执行结果)"></el-option>
            <el-option :value="20" label="异步运行(异步执行用例,后台运行,执行结束后报告列表查看)"></el-option>
          </el-select>
        </el-form-item>

        <el-form-item label="运行环境" prop="base_url">
          <el-select v-model="state.runForm.env_id" placeholder="选择环境" filterable style="width:100%">
            <el-option :value="0" label="自带环境">自带环境</el-option>
            <el-option
                v-for="item in state.envList"
                :key="item.id"
                :label="`${item.name}(${item.domain_name})`"
                :value="item.id">
              <span style="float: left">{{ `${item.name}(${item.domain_name})` }}</span>
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
            <span class="dialog-footer">
              <el-button @click="state.showRunPage = !state.showRunPage">取 消</el-button>
              <el-button type="primary" :loading="state.runApiLoading" @click="runApi">运 行</el-button>
            </span>
      </template>
    </el-dialog>

    <!--  测试报告  -->
    <el-dialog
        draggable
        v-if="state.showReportDialog"
        v-model="state.showReportDialog"
        width="90%"
        top="5vh"
        destroy-on-close
        :close-on-click-modal="false">
      <template #header>
        <strong>报告详情</strong>
        <!--      <el-button class="ml5" style="font-size: 12px" type="primary" link @click="state.showLog=!state.showLog">-->
        <!--        执行日志-->
        <!--      </el-button>-->
      </template>

      <ReportDetail :report-id="state.reportInfo.id" ref="reportDetailRef"/>

    </el-dialog>

    <!--  关系弹窗  -->
    <ApiRelationGraph ref="ApiRelationGraphRef"></ApiRelationGraph>

    <!-- postman导入  -->
    <el-dialog
        draggable
        v-model="state.showImportPage"
        @closed="closeImportPage"
        width="500px"
        top="8vh"
        title="导入"
        :close-on-click-modal="false">

      <el-form
          :rules="state.importRules"
          ref="importFormRef"
          :model="state.importForm"
          label-width="100px">

        <el-form-item label="所属项目" prop="project_id">
          <el-select
              v-model="state.importForm.project_id" placeholder="选择归属项目"
              clearable
              filterable
              style="width: 80%;" @change="selectProject">
            <el-option
                v-for="project in state.projectList"
                :key="project.id"
                :label="project.name"
                :value="project.id">
              {{ project.name }}
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="所属模块" prop="module_id">
          <el-select
              v-model="state.importForm.module_id"
              placeholder="选择模块"
              filterable style="width: 80%;"
          >
            <el-option
                v-for="modules in state.moduleList"
                :key="modules.id"
                :label="modules.name"
                :value="modules.id">
              {{ modules.name }}
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="上传文件">
          <el-upload
              ref="uploadRef"
              action="#"
              accept=".json"
              :limit="1"
              :drag="true"
              :on-change="onChangeLoad"
              :on-remove="handleRemove"
              :before-upload="beforeUpload"
              :file-list="fileList"
              :auto-upload="false"
              list-type="text"
              class="custom-upload">
            <div slot="empty">
              <el-icon class="el-icon--upload">
                <UploadFilled/>
              </el-icon>
              <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
            </div>
            <template #tip>
              <span style="opacity: 0.8;">目前只支持postman导出的json文件</span>
            </template>
          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="closeImportPage">取消</el-button>
          <el-button type="primary" @click="submitUpload" :loading="state.importButtonStart">导入</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="apiInfoList">
import {defineAsyncComponent, h, onMounted, watch, reactive, ref} from 'vue';
import {
  ElButton,
  ElDropdown,
  ElDropdownItem,
  ElDropdownMenu,
  ElIcon,
  ElMessage,
  ElMessageBox,
  ElTag
} from 'element-plus';
import {MoreFilled, UploadFilled} from "@element-plus/icons"
import {useApiInfoApi} from "/@/api/useAutoApi/apiInfo";
import {useRouter} from "vue-router";
import {useEnvApi} from "/@/api/useAutoApi/env";
import {useModuleApi} from "/@/api/useAutoApi/module";
import {useProjectApi} from "/@/api/useAutoApi/project";
import {getMethodColor, getStatusColor} from "/@/utils/case";
import {storeToRefs} from 'pinia';
import {useUserInfo} from '/@/stores/userInfo';
import ApiRelationGraph from "/@/components/RelationGraph/ApiRelationGraph.vue";


const ReportDetail = defineAsyncComponent(() => import("/@/components/Z-Report/ApiReport/ReportInfo/ReportDetail.vue"))

const reportDetailRef = ref();
const ApiRelationGraphRef = ref();
const importFormRef = ref();
const uploadRef = ref();
const fileList = ref([]);
const tableRef = ref();
const router = useRouter();
const stores = useUserInfo();
const {userInfos} = storeToRefs(stores);
const state = reactive({
  columns: [
    {label: '', columnType: 'selection', align: 'center', width: 'auto', show: true},
    {label: '序号', columnType: 'index', align: 'center', width: '60', show: true},
    // {key: 'id', label: 'ID', columnType: 'string', align: 'center', width: '60', show: true},
    {
      key: 'name', label: '用例名', align: 'center', width: '', show: true,
      render: ({row}) => h(ElButton, {
        link: true,
        type: "primary",
        onClick: () => {
          onOpenSaveOrUpdate("update", row)
        }
      }, () => row.name)
    },
    {
      key: 'method', label: '请求方式', align: 'center', width: '90', show: true,
      render: ({row}) => h(ElTag, {
        type: "",
        style: {"background": getMethodColor(row.method), color: "#ffffff",}
      }, () => row.method)
    },
    {key: 'url', label: '请求地址', align: 'center', width: 'auto', show: true},
    {key: 'project_name', label: '所属项目', align: 'center', width: 'auto', show: true},
    {key: 'module_name', label: '所属模块', align: 'center', width: 'auto', show: true},
    {
      key: 'status', label: '接口状态', align: 'center', width: '90', show: true,
      render: ({row}) => {
        let statusText = '';
        switch (row.status) {
          case 10:
            statusText = '开发中';
            break;
          case 20:
            statusText = '测试中';
            break;
          case 30:
            statusText = '已发布';
            break;
          case 40:
            statusText = '将废弃';
            break;
          default:
            row.status = 10;
            statusText = '开发中';
        }
        return h('div', {style: {alignItems: 'center'}}, [
          h('span', {
            style: {
              position: 'relative',
              top: '-2px',
              right: '5px',
              display: 'inline-block',
              width: '6px',
              height: '6px',
              verticalAlign: 'middle',
              borderRadius: '50%',
              backgroundColor: getStatusColor(row.status)
            }
          }),
          h('span', {}, statusText)
        ]);
      }
    },
    // {key: 'config_id', label: '关联配置', align: 'center', width: '100', show: true},
    {key: 'updation_date', label: '更新时间', align: 'center', width: '100', show: true},
    {key: 'updated_by_name', label: '更新人', align: 'center', width: '100', show: true},
    // {key: 'creation_date', label: '创建时间', align: 'center', width: '100', show: true},
    // {key: 'created_by_name', label: '创建人', align: 'center', width: '100', show: true},
    {
      label: '操作', fixed: 'right', width: '190', align: 'center',
      render: ({row}) => h("div", null, [
        h(ElButton, {
          type: "success",
          onClick: () => {
            onOpenRunPage(row)
          }
        }, () => '运行'),

        h(ElButton, {
          type: "warning",
          onClick: () => {
            copyApi(row)
          }
        }, () => '复制'),

        h(ElDropdown, {
              style: {
                verticalAlign: "middle",
                marginLeft: "12px"
              }
            },
            {
              default: () => h(ElButton, {
                style: {},
                link: true,
                icon: MoreFilled
              }),
              dropdown: () => h(ElDropdownMenu, {
                    style: {
                      minWidth: "100px"
                    },
                  },
                  {
                    default: () => [
                      h(ElDropdownItem, {
                        style: {
                          color: "var(--el-color-primary)"
                        },
                        onClick: () => {
                          onOpenSaveOrUpdate("update", row)
                        }
                      }, () => '编辑'),
                      h(ElDropdownItem, {
                        style: {
                          color: "#626aef"
                        },
                        onClick: () => {
                          viewRelationGraph(row)
                        }
                      }, () => '血缘关系'),
                      h(ElDropdownItem, {
                        style: {
                          color: "var(--el-color-danger)"
                        },
                        onClick: () => {
                          deleted(row)
                        }
                      }, () => '删除'),
                    ]
                  }
              )
            }
        ),
      ])
    },
  ],
  project_id: '',
  listData: [],
  tableLoading: false,
  total: 0,
  listQuery: {
    page: 1,
    pageSize: 12,
    project_id: null,
    name: '',
    created_by: null,
  },
  selectionData: [],
  // run test apiInfo
  showRunPage: false,
  runApiLoading: false,
  envList: [],
  runForm: {
    id: null,
    ids: [],
    env_id: null,
    run_type: "api",
    run_mode: 10,
    api_run_mode: "one",  // one, batch
  },
  // report
  showReportDialog: false,
  reportInfo: {},

  //project
  projectList: [],
  projectQuery: {
    page: 1,
    pageSize: 12,
    project_id: null
  },
  //module
  moduleList: [],
  moduleQuery: {
    page: 1,
    pageSize: 12,
    name: '',
    project_id: null
  },

  module_project: {},

  // import
  showImportPage: false,
  importButtonStart: false,
  importForm: {
    file_info: {
      raw: '',
      name: '',
    },
    project_id: '',
    module_id: '',
    user_id: userInfos.id,
  },
  importRules: {
    project_id: [{required: true, message: '请选择项目', trigger: 'blur'}],
    module_id: [{required: true, message: '请选择模块', trigger: 'blur'}],
  },
  // oneSelf
  oneSelf: false,
  //Relation
  showApiRelation: false,
  relationData: [],
});


// 初始化表格数据
const getList = () => {
  tableRef.value.openLoading()
  useApiInfoApi().getList(state.listQuery)
      .then(res => {
        state.listData = res.data.rows
        state.total = res.data.rowTotal
        tableRef.value.closeLoading()
      }).catch(() => {
    tableRef.value.closeLoading()
  })
};

// 选择用例
const selectionChange = (val) => {
  state.selectionData = val
}
// 获取选中用例
const getSelectionData = () => {
  return state.selectionData
}
// 新增或修改
const onOpenSaveOrUpdate = (editType, row) => {
  let query = {}
  query.editType = editType
  if (query.editType === 'save') {
    query.timestamp = new Date().getTime()
  }
  if (row) query.id = row.id
  router.push({name: 'EditApiInfo', query: query})
};

//复制
const copyApi = (row) => {
  useApiInfoApi().copyApi({id: row.id}).then(() => {
    getList()
    ElMessage.success('复制成功 🎉')
  })
}

// 删除
const deleted = (row) => {
  ElMessageBox.confirm('是否删除该条数据, 是否继续?', '提示', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  })
      .then(() => {
        useApiInfoApi().deleted({id: row.id})
            .then(() => {
              ElMessage.success('删除成功');
              getList()
            })
      })
      .catch(() => {
      });
};

// 打开运行页面
const onOpenRunPage = (row) => {
  state.showRunPage = true;
  state.runForm.api_run_mode = 'one'
  state.runForm.id = row.id;
  getEnvList();
};

// 打开运行页面
const onOpenBatchRunPage = () => {
  state.showRunPage = true;
  state.runForm.api_run_mode = 'batch'
  state.runForm.ids = state.selectionData.map((item) => item.id);
  getEnvList();
};
// 获取环境信息
const getEnvList = () => {
  useEnvApi().getList({page: 1, pageSize: 1000})  // 请求数据写死，后面优化
      .then(res => {
        state.envList = res.data.rows
      })
}
// 运行测试用例
const runApi = () => {
  state.runApiLoading = !state.runApiLoading;
  useApiInfoApi().runApi(state.runForm)
      .then((res) => {
        if (state.runForm.run_mode === 10 && state.runForm.api_run_mode === 'one') {
          ElMessage.success('运行成功');
          state.reportInfo = res.data
          // console.log(state.reportInfo, 'state.reportInfo')
          state.showReportDialog = !state.showReportDialog;
          // reportDetailRef.value.showReport()
          state.showRunPage = !state.showRunPage;
        } else {
          ElMessage.success("执行成功~");
          state.showRunPage = !state.showRunPage;
        }
        state.runApiLoading = !state.runApiLoading;
      })
      .catch((exc) => {
        console.log(exc)
        state.runApiLoading = !state.runApiLoading;
      })
}

// -------------- 导入 ------------
// 打开导入页面
const openImportPage = () => {
  state.showImportPage = !state.showImportPage
  state.importForm.project_id = ''
  state.importForm.module_id = ''
  state.importForm.file_info.raw = ''
  state.importForm.file_info.name = ''
}
const closeImportPage = () => {
  if (uploadRef.value) {
    uploadRef.value.clearFiles();
  }
  state.showImportPage = false
}
// 文件状态改变时的处理函数
const onChangeLoad = (file, fileList) => {
  // 检查文件类型是否为JSON
  if (!file.raw.type.startsWith('application/json')) {
    ElMessage.error('请选择json文件导入！');
    fileList.splice(fileList.indexOf(file), 1); // 移除无效文件
    state.importForm.file_info.raw = ''; // 清除文件引用
    state.importForm.file_info.name = '';
  }
  // 直接保存文件对象
  state.importForm.file_info.raw = file.raw;
  state.importForm.file_info.name = file.name;
  // 不需要在前端解析json文件 把解析过程放到后端
  /*const reader = new FileReader();
  reader.readAsText(file.raw, 'UTF-8');
  reader.onload = (e) => {
    try {
      const content = JSON.parse(e.target.result);
      state.importForm.file_info.raw = content;
      state.importForm.file_info.name = file.name;
    } catch (error) {
      ElMessage.error('文件内容解析失败，请确保文件是有效的 JSON 格式');
      fileList.splice(fileList.indexOf(file), 1); // 移除无效文件
    }
  };*/
};

// 删除文件处理
const handleRemove = (file, fileList) => {
  state.importForm.file_info.raw = null;
  state.importForm.file_info.name = '';
  uploadRef.value.clearFiles();
};

// 上传前的验证
const beforeUpload = (file) => {
  const isJSON = file.name.endsWith('.json');
  if (!isJSON) {
    ElMessage.error('只能上传 JSON 文件');
    return false;
  }
  return true;
};

// 文件上传
const submitUpload = () => {
  state.importButtonStart = true
  importFormRef.value.validate(async (vai) => {
    if (vai) {
      if (!state.importForm.file_info.raw) {
        ElMessage.info('请选择上传文件！')
        state.importButtonStart = false
        return
      }
      try {
        let formData = new FormData()
        formData.append('file', state.importForm.file_info.raw)
        formData.append('project_id', state.importForm.project_id)
        formData.append('module_id', state.importForm.module_id)
        let res = await useApiInfoApi().postman2case(formData)
        ElMessage.success(`成功导入${res.data}条用例！`)
        state.importButtonStart = false
        state.showImportPage = false
        getList()
      } catch (e) {
        state.importButtonStart = false
      }
    } else {
      state.importButtonStart = false
      ElMessage.error('请上传符合要求的json文件！');
    }
  })
}

// 获取项目列表
const getProjectList = () => {
  useProjectApi().getList(state.projectQuery) // 请求数据写死，后面优化
      .then(res => {
        state.projectList = res.data.rows
      })
}
// 选择项目
const selectProject = (project_id) => {
  state.moduleQuery.project_id = project_id
  state.moduleList = state.module_project[project_id]
  state.importForm.module_id = ''
  // getModuleList()
}

//  ----------------module start-------------------------------------
// 获取模块列表
const getModuleList = () => {
  useModuleApi().getList(state.moduleQuery) // 请求数据写死，后面优化
      .then(res => {
        state.moduleList = res.data.rows
        // 组件项目&模块 字典
        state.moduleList.forEach(module => {
          // 获取projectId以作为key
          let projectId = module.project_id;
          // 如果organizedData中还没有这个projectId对应的entry，则创建一个新的对象
          if (!state.module_project[projectId]) {
            state.module_project[projectId] = [];
          }
          // 将moduleId与moduleName添加到对应projectId下的对象中
          state.module_project[projectId].push({
            "id": module.id,
            "name": module.name,
            "project_id": module.project_id,
            "project_name": module.project_name,
          });
        });

      })
}

// 只看自己
const oneSelfChange = (val) => {
  state.listQuery.created_by = val ? userInfoStore.userInfos.id : null
  getList()
}

const viewRelationGraph = (row) => {
  ApiRelationGraphRef.value.openDialog(row.id, "api")
}

defineExpose({
  getSelectionData,
})

// 页面加载时
onMounted(() => {
  getList();
  getModuleList()
  getProjectList()
});

</script>

<style lang="scss" scoped>
.file-input-container {
  display: inline-block;
  max-width: 100%;

  .file-input {
    display: flex;
    align-items: center;
    padding: var(--spacing-xs);

    .file-input__native {
      opacity: 0;
      position: absolute;
      width: 0;
      height: 0;
      pointer-events: none;
    }

    .file-input__fake {
      position: relative;
      height: 20px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      cursor: pointer;
      background-color: #F2F2F2;
      min-width: 100px;
      color: #6B6B6B;
      font-weight: 600;

      &:hover {
        color: #212121;
        background-color: #E6E6EE;
      }
    }

    .btn {
      box-sizing: border-box;
      border-radius: 4px;
    }

    .file-input__name {
      box-sizing: border-box;
      display: flex;
      min-width: 0;
      height: 24px;
      align-items: center;
      border-radius: 4px;
      border: 1px solid #E6E6E6;
      font-size: 12px;
      font-family: "Inter", system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica, Arial, sans-serif;
      color: #212121;
      background-color: transparent;
      padding: 4px 2px;

      .file-input__name__title {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      .file-input__name__delete-icon {
        display: flex;
        align-items: center;
        margin-left: 8px;
        padding-right: 2px;
        cursor: pointer;
        color: #212121;
      }
    }
  }
}

.flex-container {
  display: flex;
  flex-wrap: nowrap; // 确保子元素不会换行
  align-items: center; // 垂直居中对齐
  gap: 10px; // 元素之间的间距

  .sift_left,
  .sift_right {
    display: flex;
    align-items: center;
  }

  .sift_right {
    width: 130px;
  }
}

.custom-upload ::v-deep .el-upload-dragger {
  width: 300px;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.custom-upload ::v-deep .el-icon--upload,
.custom-upload :deep(.el-icon--upload) {
  color: #e0cb6d;
}
.el-upload__text {
  margin-top: -18px;
}

</style>
